const streams = require('streamroller');
const os = require('os');

const eol = os.EOL;

function openTheStream(filename, pattern, options) {
	const stream = new streams.DateRollingFileStream(
		filename,
		pattern,
		options
	);
	stream.on('error', (err) => {
		console.error('log4js.dateFileAppender - Writing to file %s, error happened ', filename, err); //eslint-disable-line
	});
	stream.on("drain", () => {
		process.emit("log4js:pause", false);
	});
	return stream;
}

/**
 * File appender that rolls files according to a date pattern.
 * @param filename base filename.
 * @param pattern the format that will be added to the end of filename when rolling,
 *          also used to check when to roll files - defaults to '.yyyy-MM-dd'
 * @param layout layout function for log messages - defaults to basicLayout
 * @param options - options to be passed to the underlying stream
 * @param timezoneOffset - optional timezone offset in minutes (default system local)
 */
function appender(
	filename,
	pattern,
	layout,
	options,
	timezoneOffset,
	levels
) {
	// the options for file appender use maxLogSize, but the docs say any file appender
	// options should work for dateFile as well.
	options.maxSize = options.maxLogSize;

	const writer = openTheStream(filename, pattern, options);
	const minLevel = levels.getLevel(options.level);
	const maxLevel = levels.getLevel( options.maxLevel, levels.FATAL);

	const app = function (logEvent) {
		if (!writer.writable) {
			return;
		}
		const eventLevel = logEvent.level;
		if (eventLevel.isGreaterThanOrEqualTo(minLevel) && eventLevel.isLessThanOrEqualTo(maxLevel)) {
			if (!writer.write(layout(logEvent, timezoneOffset) + eol, "utf8")) {
				process.emit("log4js:pause", true);
			}
		}
	};

	app.shutdown = function (complete) {
		writer.end('', 'utf-8', complete);
	};

	return app;
}

function configure(config, layouts, findAppender, levels) {
	let layout = layouts.basicLayout;
	if (config.layout) {
		layout = layouts.layout(config.layout.type, config.layout);
	}

	if (!config.alwaysIncludePattern) {
		config.alwaysIncludePattern = false;
	}

	// security default (instead of relying on streamroller default)
	config.mode = config.mode || 0o600;

	return appender(
		config.filename,
		config.pattern,
		layout,
		config,
		config.timezoneOffset,
		levels
	);
}

module.exports.configure = configure;
